<template>
  <div class='graph'>
    <div v-if="props.graphTopState" class="g-top">
      <el-button @click="retreat" type="primary">返回</el-button>
      <div class="gt-prompt">
        注:知识点名称一致的为相同知识点，在选中当前知识点时会对其他相同知识点用 ”
        <svg>
          <rect class="gtp-svg" stroke="#81b337" width="100" height="30" />
        </svg>
        “ 标识
      </div>
    </div>
    <!-- 图形 -->
    <!-- <svg class="svgContainer"></svg> -->
    <div class="fl-bottom" ref="canvas">

    </div>
    <div id="popup" style="display: none; border: 1px solid black; padding: 10px;">
      这里是弹出的div
    </div>
  </div>
</template>
<script lang='ts' setup>
import data from "./data.json"
// import dataoption from '@/template/Echarts';
import * as d3 from "d3"
import * as echarts from 'echarts';
import { onMounted, ref } from "vue"
import { useAppStore } from '@/store/modules/app'
import { useRouter, useRoute } from 'vue-router'
const canvas = ref(null)
// const earchs = () => {
//   const chartDom = canvas.value;
//   const myChart = echarts.init(chartDom);
//   myChart.setOption(dataoption.option);
// }
const router = useRouter()
const route = useRoute()
const props = defineProps({
  graphTopState: {
    // 图谱顶部内容是否展示
    type: Boolean,
    default: true
  },
  marginLeft: {
    // 图谱左侧距离
    type: Number,
    default: 200
  },
  activityData: {
    // 活动的数据。传递时，可高亮流程
    type: Array,
    default: () => []
  },
  processInstanceData: {
    // 流程实例的数据。传递时，可展示流程发起人等信息
    type: Object,
    default: () => { }
  },
  taskData: {
    // 任务实例的数据。传递时，可展示 UserTask 审核相关的信息
    type: Array,
    default: () => []
  }
})
const appStore = useAppStore()
appStore.setFooter(false) // 配置当前页面不显示底部版权信息
onMounted(() => {
  chart()
})
// chart()

const retreat = () => {
  router.go(-1)
}
function chart() {
  const graphClientWidth = window.document.querySelector('.graph').clientWidth
  // Specify the charts’ dimensions. The height is variable, depending on the layout.
  // const width = 928;
  const width = graphClientWidth || 928
  const marginTop = 50;
  const marginRight = 10;
  const marginBottom = 50;
  const marginLeft = props.marginLeft;
  // Rows are separated by dx pixels, columns by dy pixels. These names can be counter-intuitive
  // (dx is a height, and dy a width). This because the tree must be viewed with the root at the
  // “bottom”, in the data domain. The width of a column is based on the tree’s height.
  const root = d3.hierarchy(data);
  const dx = 50;
  const dy = (width - marginRight - marginLeft) / (1 + root.height);

  // Define the tree layout and the shape for links.
  const tree = d3.tree().nodeSize([dx, dy]);
  const diagonal = d3.linkHorizontal().x(d => d.y).y(d => d.x);

  // Create the SVG container, a layer for the links and a layer for the nodes.
  // const svg = d3.create("svg")
  // .attr("class", "svgContainer")
  const svg = d3.select(window.document.querySelector('.svgContainer'))
    .attr("width", width)
    .attr("height", dx)
    .attr("viewBox", [-marginLeft, -marginTop, width, dx])
    .attr("style", "max-width: 100%; height: auto; font: 10px sans-serif; user-select: none;");
  // 定义缩放行为
  // var zoom = d3.zoom()
  //   // .scaleExtent([1, 4]) // 缩放范围
  //   .on('zoom', function (current) {
  //     console.log('current：', current)
  //     svg.attr('transform', `translate(${current.transform.x},${current.transform.y}) scale(${current.transform.k})`)
  //   })
  // svg.call(
  //   d3.zoom().on('zoom', function (current) {
  //     console.log('current：', current)
  //     svg.attr('transform', `translate(${current.transform.x},${current.transform.y}) scale(${current.transform.k})`)
  //   })
  // )
  // d3.selection.call(d3.zoom().on("zoom", function () {
  //   svg.attr("transform", d3.event.transform);
  // }));
  // 绑定缩放行为到SVG
  // svg.call(zoom);

  // svg.on('click', (event) => {
  //   console.log(event)
  //   console.log(data)
  // })

  const gLink = svg.append("g")
    .attr("fill", "none")
    .attr("stroke", "#555")
    .attr("stroke-opacity", 0.4)
    .attr("stroke-width", 1.5);

  const gNode = svg.append("g")
    .attr("cursor", "pointer")
    .attr("pointer-events", "all");

  function update(event, source) {
    const duration = event?.altKey ? 2500 : 250; // hold the alt key to slow down the transition
    const nodes = root.descendants().reverse()
    const links = root.links()
    // Compute the new tree layout.
    tree(root)
    let left = root;
    let right = root;
    root.eachBefore(node => {
      if (node.x < left.x) left = node;
      if (node.x > right.x) right = node;
    });
    const height = right.x - left.x + marginTop + marginBottom;
    const transition = svg.transition()
      .duration(duration)
      .attr("height", height)
      .attr("viewBox", [-marginLeft, left.x - marginTop, width, height])
      .tween("resize", window.ResizeObserver ? null : () => () => svg.dispatch("toggle"));

    // Update the nodes…
    const node = gNode.selectAll("g")
      .data(nodes, d => d.id);
    const rect = gNode.selectAll("rect")
      .data(nodes, d => d.id);
    console.log(node)
    console.log(rect)
    // 添加点击事件
    svg.on("click", function (d) {
      // d.srcElement.__data__为false，点击项目为空白区域
      if (!d.srcElement.__data__) {
        d3.selectAll(rect)
          .style("stroke", "#f5f7f9")
      } else {
        if (d.srcElement.__data__.data.children) return
        d3.selectAll(rect)
          .style("stroke", "#f5f7f9")
          .filter(function (e) { return e.data.name === d.srcElement.__data__.data.name })
          .style("stroke", "#81b337")
          .style("stroke-width", 3)
          .style("fill", "transparent")
          .style("stroke-dasharray", "4 4")
          .filter(function (e) { return e.data.value === d.srcElement.__data__.data.value })
          .style("stroke-dasharray", "none")
      }
    });
    // Enter any new nodes at the parent's previous position.
    const nodeEnter = node.enter().append("g")
      .attr("transform", d => `translate(${source.y0},${source.x0})`)
      .attr("fill-opacity", 0)
      .attr("stroke-opacity", 0)
      .on("click", (event, d) => {
        d.children = d.children ? null : d._children;
        update(event, d);
      });
    // nodeEnter.append("circle")
    // .attr("r", 2.5)
    // .attr("r", 25)
    nodeEnter.append("rect")
      // .attr('rx', d => d.parent ? 5 : 10)
      // .attr('ry', d => d.parent ? 5 : 10)
      .style('rx', function (d) {
        if (!d.parent) return 10
        else if (d._children) return 5
        else return 0
      })
      .style('ry', function (d) {
        if (!d.parent) return 10
        else if (d._children) return 5
        else return 0
      })
      // .attr('x', -50)
      // .attr('y', -15)
      .attr('x', d => d.parent ? -50 : -100)
      .attr('y', d => d.parent ? -20 : -35)
      // .attr('width', 100)
      .attr('width', d => d.parent ? 100 : 200)
      // .attr('width', d => console.log(d))
      .attr('height', d => d.parent ? 40 : 70)
      // .attr('height', 30)
      .style('fill', function (d) {
        if (!d.parent) return "#50c28b"
        else if (d._children) return "#ffffff"
        else return "#f5f7f9"
      })

    // .attr("stroke-width", 10)
    // .attr("stroke", "black")

    nodeEnter.append("text")
      // .attr('clip-path', 'rect') // 使图片在圆形边界内显示
      .attr("dy", "0.31em")

      // .attr("x", d => d._children ? -6 : 6)
      // .attr("x", -25)
      // .attr("text-align", "center")
      // .attr("text-anchor", d => d._children ? "end" : "start")
      .attr('text-anchor', 'middle') // 水平居中
      // .attr('dominant-baseline', 'middle') // 垂直居中
      .attr('font-weight', 'lighter')
      .text(d => d.data.name)
      // .attr("stroke-linejoin", "round")
      // .attr("stroke-width", 3)
      // .attr("stroke", "white")
      // .attr("paint-order", "stroke")
      .style('font-weight', function (d) {
        if (!d.parent) return 'normal'
        else if (d._children) return 'lighter'
      })
      .style('font-size', function (d) {
        if (!d.parent) return 40
        else if (d._children) return 20
        else return 20
      })
    // Transition nodes to their new position.
    const nodeUpdate = node.merge(nodeEnter).transition(transition)
      .attr("transform", d => `translate(${d.y},${d.x})`)
      .attr("fill-opacity", 1)
      .attr("stroke-opacity", 1);

    // Transition exiting nodes to the parent's new position.
    const nodeExit = node.exit().transition(transition).remove()
      .attr("transform", d => `translate(${source.y},${source.x})`)
      .attr("fill-opacity", 0)
      .attr("stroke-opacity", 0);

    // Update the links…
    const link = gLink.selectAll("path")
      .data(links, d => d.target.id);

    // Enter any new links at the parent's previous position.
    // 在父对象的上一个位置输入任何新链接。
    const linkEnter = link.enter().append("path")
      .attr("d", d => {
        console.log(d)
        console.log(source)
        // const o = { x: source.x0, y: source.y0 };
        const o = { x: source.x, y: source.y };
        return diagonal({ source: o, target: o });
      });

    // Transition links to their new position.
    // 过渡链接到他们的新职位。
    link.merge(linkEnter).transition(transition)
      .attr("d", diagonal);

    // Transition exiting nodes to the parent's new position.
    link.exit().transition(transition).remove()
      .attr("d", d => {
        const o = { x: source.x, y: source.y };
        return diagonal({ source: o, target: o });
      });

    // Stash the old positions for transition.
    root.eachBefore(d => {
      d.x0 = d.x;
      d.y0 = d.y;
    });
  }

  // Do the first update to the initial configuration of the tree — where a number of nodes
  // are open (arbitrarily selected as the root, plus nodes with 7 letters).
  root.x0 = dy / 2;
  root.y0 = 0;
  root.descendants().forEach((d, i) => {
    d.id = i;
    d._children = d.children;
    if (d.depth && d.data.name.length !== 7) d.children = null;
  });
  update(null, root);
  console.log(svg.node())
  return svg.node();


}

</script>
<style lang='scss' scoped>
.graph {
  width: 100%;
  height: 100%;

  .g-top {
    margin: 20px 0 0 20px;
    height: 30px;
    display: flex;
    justify-content: flex-start;
    align-items: center;

    .gt-prompt {
      display: flex;
      justify-content: center;
      align-items: center;
      margin-left: 20px;
      color: #bd3124;

      svg {
        width: 100px;
        height: 30px;

        .gtp-svg {
          stroke-width: 3;
          fill: transparent;
          stroke-dasharray: 4 4;
        }
      }

    }
  }

  .fl-bottom {
    width: 100vh;
    height: 100vw;
    background-color: #f8f9f8;
    position: relative;
  }

  .svgContainer {}
}
</style>
